package com.zl.learning.lambada;

import com.alibaba.fastjson.JSON;
import com.google.gson.Gson;
import org.junit.Test;

import java.util.*;
import java.util.function.Function;
import java.util.function.IntSupplier;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class StreamTest2 {

    @Test
    public void test1() {
        Map<String, String> m = new HashMap<>();
        Map<String, String> m1 = new HashMap<>();
        Map<String, String> m2 = new HashMap<>();
        m.put("a", "aa");
        m1.put("b", "bb");
        m2.put("c", "cc");
        List<Map<String, String>> ms = new ArrayList<>();
        ms.add(m);
        ms.add(m1);
        ms.add(m2);
        System.out.println(new Gson().toJson(ms));
    }

    @Test
    public void test2() {
//        Map<String, String> m = new HashMap<>();
//        m.put("a", "aa");
//        m.put("b", "bb");
//        m.put("c", "cc");
//        List<Map<String, String>> ms = new ArrayList<>(m.entrySet().stream().map(r -> {
//            HashMap<String, String> map = new HashMap<>();
//            map.put(r.getKey(), r.getValue());
//            return map;
//        }).collect(Collectors.toList()));
        Map<String, String> m = Map.ofEntries(Map.entry("a", "aa"), Map.entry("b", "bb"), Map.entry("c", "cc"));
        System.out.println(JSON.toJSONString(m));
        List<Map<String, String>> ms = m.entrySet().stream().map(Map::ofEntries).collect(Collectors.toList());
        System.out.println(new Gson().toJson(ms));
    }

    @Test
    public void test3() {
        Map<String, String> m = new HashMap<>();
        m.put("a", "aa");
        m.put("b", "bb");
        m.put("c", "cc");
        List<Map<String, String>> ms = m.entrySet().stream().map(r -> new HashMap<String, String>(new HashMap<String, String>() {{
            put(r.getKey(), r.getValue());
        }})).collect(Collectors.toList());
        System.out.println(new Gson().toJson(ms));
    }

    @Test
    public void test4() {
//        List<Map<String, String>> ms = new ArrayList<>();
//        ms.add(new HashMap<String, String>() {{
//            put("a", "aaa");
//        }});
//        ms.add(new HashMap<String, String>() {{
//            put("b", "bbb");
//        }});
//        ms.add(new HashMap<String, String>() {{
//            put("c", "ccc");
//        }});
        List<Map<String, String>> ms = List.of(Map.of("a", "aaa"), Map.of("b", "bbb"), Map.of("c", "ccc"));
        System.out.println(new Gson().toJson(ms));
    }

    @Test
    public void test5() {
        List<Integer> is = Arrays.asList(5, 3, 6, 9, 7, 10);

        int max = is.stream().reduce(is.get(0), (e1, e2) -> e1 - e2 <= 0 ? e1 : e2);
        System.out.println(max);

        int sum = is.stream().reduce(0, Integer::sum);
        System.out.println(sum);

        int min = is.stream().reduce(is.get(0), Integer::min);
        System.out.println(min);

        Function<String, Integer> stringToInteger = Integer::parseInt;
        int a = stringToInteger.apply("111111");
        System.out.println(a);

        String b = "HelloWorld";
        Arrays.stream(b.split("")).map(w -> w.split("")).flatMap(Arrays::stream).forEach(System.out::println);
    }

    @Test
    public void test6() {
        List<Integer> numbers1 = Arrays.asList(1, 2, 3);
        List<Integer> numbers2 = Arrays.asList(3, 4);
        List<int[]> pairs = numbers1.stream().flatMap(i -> numbers2.stream().filter(j -> (i + j) % 3 == 0).map(j -> new int[]{i, j})).collect(Collectors.toList());
        System.out.println(pairs);
    }

    @Test
    public void test7() {
        List<Integer> is = Arrays.asList(5, 3, 6, 9, 7, 10);
        int a = is.stream().reduce(Integer::max).get();
        int b = is.stream().reduce(Integer::min).get();
        System.out.println(a);
        System.out.println(b);
        IntSummaryStatistics menuStatistics = is.stream().collect(Collectors.summarizingInt(r -> r));
        is.stream().mapToInt(r -> r).sum();
        System.out.println(menuStatistics);
    }

    @Test
    public void test8() {
        Stream<int[]> pythagoreanTriples =
                IntStream.rangeClosed(1, 100).boxed()
                        .flatMap(a ->
                                IntStream.rangeClosed(a, 100)
                                        .filter(b -> Math.sqrt(a * a + b * b) % 1 == 0)
                                        .mapToObj(b ->
                                                new int[]{a, b, (int) Math.sqrt(a * a + b * b)})
                        );
        pythagoreanTriples.limit(5).forEach(t -> System.out.println(t[0] + ", " + t[1] + ", " + t[2]));


        Stream<double[]> pythagoreanTriples2 =
                IntStream.rangeClosed(1, 100).boxed()
                        .flatMap(a ->
                                IntStream.rangeClosed(a, 100)
                                        .mapToObj(
                                                b -> new double[]{a, b, Math.sqrt(a * a + b * b)})
                                        .filter(t -> t[2] % 1 == 0));

    }

    @Test
    public void test9() {
        Stream.iterate(0, n -> n + 2)
                .limit(10)
                .forEach(System.out::println);
    }

    @Test
    public void test10() {
        Stream.iterate(new int[]{0, 1},
                t -> new int[]{t[1], t[0] + t[1]})
                .limit(20)
                .forEach(t -> System.out.println("(" + t[0] + "," + t[1] + ")"));

        Stream.iterate(new int[]{0, 1},
                t -> new int[]{t[1], t[0] + t[1]})
                .limit(10)
                .map(t -> t[0])
                .forEach(System.out::println);
    }

    @Test
    public void test11() {
//        Stream.generate(Math::random).limit(5).forEach(System.out::println);
//        IntStream.rangeClosed(0,100).forEach(System.out::println);
//        new Random().ints().limit(10).forEach(System.out::println);
        new Random().ints(10, 0, 10).forEach(System.out::println);
    }

    @Test
    public void test12() {
        IntSupplier fib = new IntSupplier() {
            private int previous = 0;
            private int current = 1;

            @Override
            public int getAsInt() {
                int oldPrevious = this.previous;
                int nextValue = this.previous + this.current;
                this.previous = this.current;
                this.current = nextValue;
                return oldPrevious;
            }
        };
        IntStream.generate(fib).limit(10).forEach(System.out::println);
    }

    @Test
    public void test13() {
        String a = "中国人";
        System.out.println(a.charAt(0));
    }
}
